From 1041f93f7ff95f603260d4edf41bc372697d4206 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 25 Sep 2014 23:05:15 -0400 Subject: [PATCH] inspector: life-cycle fixes When closing the inspector before the main window, we must take care to sever all signal connections and weak refs, otherwise things will go bad when the window is closed later. --- gtk/inspector/classes-list.c | 28 ++++++++++++++++++----- gtk/inspector/css-editor.c | 43 +++++++++++++++++++++++++++++++++--- gtk/inspector/prop-list.c | 10 ++++----- gtk/inspector/widget-tree.c | 6 ++--- 4 files changed, 70 insertions(+), 17 deletions(-) diff --git a/gtk/inspector/classes-list.c b/gtk/inspector/classes-list.c index 2d21265aae..1fc313082c 100644 --- a/gtk/inspector/classes-list.c +++ b/gtk/inspector/classes-list.c @@ -225,20 +225,23 @@ gtk_inspector_classes_list_init (GtkInspectorClassesList *cl) gtk_widget_init_template (GTK_WIDGET (cl)); } -static void remove_dead_object (gpointer data, GObject *dead_object); +static void gtk_inspector_classes_list_remove_dead_object (gpointer data, GObject *dead_object); static void cleanup_context (GtkInspectorClassesList *cl) { if (cl->priv->context) - g_object_weak_unref (G_OBJECT (cl->priv->context), remove_dead_object, cl); + { + g_object_weak_unref (G_OBJECT (cl->priv->context),gtk_inspector_classes_list_remove_dead_object, cl); + cl->priv->context = NULL; + } - gtk_list_store_clear (cl->priv->model); - cl->priv->context = NULL; + if (cl->priv->model) + gtk_list_store_clear (cl->priv->model); } static void -remove_dead_object (gpointer data, GObject *dead_object) +gtk_inspector_classes_list_remove_dead_object (gpointer data, GObject *dead_object) { GtkInspectorClassesList *cl = data; @@ -267,7 +270,7 @@ gtk_inspector_classes_list_set_object (GtkInspectorClassesList *cl, cl->priv->context = gtk_widget_get_style_context (GTK_WIDGET (object)); - g_object_weak_ref (G_OBJECT (cl->priv->context), remove_dead_object, cl); + g_object_weak_ref (G_OBJECT (cl->priv->context), gtk_inspector_classes_list_remove_dead_object, cl); hash_context = get_hash_context (cl); if (hash_context) @@ -290,10 +293,23 @@ gtk_inspector_classes_list_set_object (GtkInspectorClassesList *cl, read_classes_from_style_context (cl); } +static void +gtk_inspector_classes_list_finalize (GObject *object) +{ + GtkInspectorClassesList *cl = GTK_INSPECTOR_CLASSES_LIST (object); + + cleanup_context (cl); + + G_OBJECT_CLASS (gtk_inspector_classes_list_parent_class)->finalize (object); +} + static void gtk_inspector_classes_list_class_init (GtkInspectorClassesListClass *klass) { GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gtk_inspector_classes_list_finalize; gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/inspector/classes-list.ui"); gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorClassesList, model); diff --git a/gtk/inspector/css-editor.c b/gtk/inspector/css-editor.c index d8f5181920..7bfaa26686 100644 --- a/gtk/inspector/css-editor.c +++ b/gtk/inspector/css-editor.c @@ -67,6 +67,9 @@ struct _GtkInspectorCssEditorPrivate guint timeout; }; +static void gtk_inspector_css_editor_remove_dead_object (gpointer data, + GObject *dead_object); + G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorCssEditor, gtk_inspector_css_editor, GTK_TYPE_BOX) static void @@ -333,6 +336,30 @@ create_provider (GtkInspectorCssEditor *ce) G_CALLBACK (show_parsing_error), ce); } +static void +destroy_provider (GtkInspectorCssEditor *ce) +{ + if (ce->priv->global) + { + gtk_style_context_remove_provider_for_screen (gdk_screen_get_default (), + GTK_STYLE_PROVIDER (ce->priv->provider)); + g_object_unref (ce->priv->provider); + ce->priv->provider = NULL; + } + else if (ce->priv->context) + { + GtkStyleProvider *provider; + + provider = g_object_get_data (G_OBJECT (ce->priv->context), + GTK_INSPECTOR_CSS_EDITOR_PROVIDER); + gtk_style_context_remove_provider (ce->priv->context, provider); + g_object_set_data (G_OBJECT (ce->priv->context), + GTK_INSPECTOR_CSS_EDITOR_PROVIDER, + NULL); + } +} + + static void gtk_inspector_css_editor_init (GtkInspectorCssEditor *ce) { @@ -398,6 +425,16 @@ finalize (GObject *object) if (ce->priv->timeout != 0) g_source_remove (ce->priv->timeout); + destroy_provider (ce); + if (ce->priv->context) + { + g_object_weak_unref (G_OBJECT (ce->priv->context), gtk_inspector_css_editor_remove_dead_object, ce); + g_object_set_data (G_OBJECT (ce->priv->context), + GTK_INSPECTOR_CSS_EDITOR_TEXT, + NULL); + ce->priv->context = NULL; + } + G_OBJECT_CLASS (gtk_inspector_css_editor_parent_class)->finalize (object); } @@ -427,7 +464,7 @@ gtk_inspector_css_editor_class_init (GtkInspectorCssEditorClass *klass) } static void -remove_dead_object (gpointer data, GObject *dead_object) +gtk_inspector_css_editor_remove_dead_object (gpointer data, GObject *dead_object) { GtkInspectorCssEditor *ce = data; @@ -447,7 +484,7 @@ gtk_inspector_css_editor_set_object (GtkInspectorCssEditor *ce, if (ce->priv->context) { - g_object_weak_unref (G_OBJECT (ce->priv->context), remove_dead_object, ce); + g_object_weak_unref (G_OBJECT (ce->priv->context), gtk_inspector_css_editor_remove_dead_object, ce); text = get_current_text (GTK_TEXT_BUFFER (ce->priv->text)); g_object_set_data_full (G_OBJECT (ce->priv->context), GTK_INSPECTOR_CSS_EDITOR_TEXT, @@ -472,7 +509,7 @@ gtk_inspector_css_editor_set_object (GtkInspectorCssEditor *ce, set_initial_text (ce); disable_toggled (ce->priv->disable_button, ce); - g_object_weak_ref (G_OBJECT (ce->priv->context), remove_dead_object, ce); + g_object_weak_ref (G_OBJECT (ce->priv->context), gtk_inspector_css_editor_remove_dead_object, ce); } // vim: set et sw=2 ts=2: diff --git a/gtk/inspector/prop-list.c b/gtk/inspector/prop-list.c index 707e4a234c..139977748e 100644 --- a/gtk/inspector/prop-list.c +++ b/gtk/inspector/prop-list.c @@ -391,14 +391,14 @@ gtk_inspector_prop_list_set_object (GtkInspectorPropList *pl, g_free (props); if (GTK_IS_WIDGET (object)) - g_signal_connect_swapped (object, "destroy", G_CALLBACK (cleanup_object), pl); + g_signal_connect_object (object, "destroy", G_CALLBACK (cleanup_object), pl, G_CONNECT_SWAPPED); /* Listen for updates */ pl->priv->notify_handler_id = - g_signal_connect (object, - pl->priv->child_properties ? "child-notify" : "notify", - G_CALLBACK (gtk_inspector_prop_list_prop_changed_cb), - pl); + g_signal_connect_object (object, + pl->priv->child_properties ? "child-notify" : "notify", + G_CALLBACK (gtk_inspector_prop_list_prop_changed_cb), + pl, 0); gtk_widget_show (GTK_WIDGET (pl)); diff --git a/gtk/inspector/widget-tree.c b/gtk/inspector/widget-tree.c index 6f3ec6ac64..8fd6130866 100644 --- a/gtk/inspector/widget-tree.c +++ b/gtk/inspector/widget-tree.c @@ -88,7 +88,7 @@ typedef struct } ObjectData; static void -remove_dead_object (gpointer data, GObject *dead_object) +gtk_widget_tree_remove_dead_object (gpointer data, GObject *dead_object) { ObjectData *od = data; @@ -113,7 +113,7 @@ object_data_free (gpointer data) gtk_tree_row_reference_free (od->row); if (od->object) - g_object_weak_unref (od->object, remove_dead_object, od); + g_object_weak_unref (od->object, gtk_widget_tree_remove_dead_object, od); g_free (od); } @@ -333,7 +333,7 @@ gtk_inspector_widget_tree_append_object (GtkInspectorWidgetTree *wt, gtk_tree_path_free (path); g_hash_table_insert (wt->priv->iters, object, od); - g_object_weak_ref (object, remove_dead_object, od); + g_object_weak_ref (object, gtk_widget_tree_remove_dead_object, od); g_free (address); -- 2.30.2